package com.share.ai.alibaba.starter.web;

import com.alibaba.cloud.ai.advisor.DocumentRetrievalAdvisor;
import com.alibaba.cloud.ai.dashscope.agent.DashScopeAgent;
import com.alibaba.cloud.ai.dashscope.agent.DashScopeAgentOptions;
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisModel;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisPrompt;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisResponse;
import com.alibaba.cloud.ai.dashscope.rag.*;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.document.Document;
import org.springframework.ai.image.*;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;

@RestController
public class AiController {
    @Autowired
    private ChatClient chatClient;

    @Autowired
    private ImageModel imageModel;

    @Autowired
    private SpeechSynthesisModel speechSynthesisModel;

    @Autowired
    private VectorStore vectorStore;

    @GetMapping("/chat")
    public String chat(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(value = "prompt", defaultValue = "一只在草地上玩耍的可爱小猫") String prompt) {
        return chatClient.prompt()
                .system("你是一位资深的Java开发专家，用简单易懂的方式回答技术问题。")//设置系统提示词
                .advisors(new QuestionAnswerAdvisor(vectorStore)) //向量数据库用于查询问题
                .functions("timeFunction") //配置functioncall
                .user(prompt)  // 用户提问
                .call()          // 调用AI
                .content();      // 获取回答

//        return chatClient.prompt()
//                .system("你是一位资深的Java开发专家，用简单易懂的方式回答技术问题。")//设置系统提示词
//                .user(prompt)  // 用户提问
//                .call().entity(Person.class);         //返回一个对象
    }

    @GetMapping("/chatTemplate")
    public String chatTemplate(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(defaultValue = "name") String name,
            @RequestParam(defaultValue = "topic") String topic) {
        // 创建模板
        String template = "为{name}用故事的方式讲解{topic}，故事要生动有趣。";
        PromptTemplate promptTemplate = new PromptTemplate(template);
        Prompt prompt = promptTemplate.create(Map.of(
                "name", name,
                "topic", topic
        ));

        //第二种创建方式
        UserMessage userMessage = new UserMessage("回答简单点,不知道就不知道,不要胡说八道");
        SystemMessage systemMessage = new SystemMessage("你是一个女性的角色,说话要温柔");
        Message profession = new SystemPromptTemplate("你是一个 {profession}").createMessage(Map.of("profession", prompt));
        Prompt prompt2 = new Prompt(List.of(userMessage, systemMessage, profession));
        return chatClient.prompt(prompt).call().content();
    }

    /**
     * 汉字转语音文件---文件下载的方式
     */
    @GetMapping("/text2audio")
    public ResponseEntity<byte[]> text2audio(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(value = "prompt", defaultValue = "你好，很高兴认识你，能简单介绍一下自己吗？") String prompt) {
        //调用模型生成语音
        SpeechSynthesisResponse response = speechSynthesisModel.call(new SpeechSynthesisPrompt(prompt));
        ByteBuffer audioData = response.getResult().getOutput().getAudio();

        //将ByteBuffer转化为字节数组---文件下载的方式
        byte[] audioBytes = new byte[audioData.remaining()];
        audioData.get(audioBytes);

        //返回音频流，mp3格式
        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header("Content-Disposition", "attachment; filename=output.mp3")
                .body(audioBytes);
    }

    /**
     * 在线播放语音接口---直接在线网页播放
     */
    @GetMapping("/text2audioPlay")
    public ResponseEntity<byte[]> text2audioPlay(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(value = "prompt", defaultValue = "你好，很高兴认识你，能简单介绍一下自己吗？") String prompt) {
        SpeechSynthesisResponse response = speechSynthesisModel.call(new SpeechSynthesisPrompt(prompt));
        ByteBuffer audioData = response.getResult().getOutput().getAudio();

        byte[] audioBytes = new byte[audioData.remaining()];
        audioData.get(audioBytes);

        //直接在线网页播放
        return ResponseEntity.ok()
                .contentType(MediaType.valueOf("audio/mpeg"))
                .body(audioBytes);
    }

    @GetMapping("/text2image")
    public void text2image(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(value = "prompt", defaultValue = "一只在草地上玩耍的可爱小猫") String prompt,
            HttpServletResponse response) throws IOException {

        ImageResponse imageResponse = imageModel.call(new ImagePrompt(prompt));
        String imageUrl = imageResponse.getResult().getOutput().getUrl();

        try (InputStream in = URI.create(imageUrl).toURL().openStream()) {
            response.setHeader("Content-Type", "image/png");
            response.getOutputStream().write(in.readAllBytes());
            response.getOutputStream().flush();
        }
    }

    @GetMapping("/text2imageUrl1")
    public String text2imageUrl1(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(value = "prompt", defaultValue = "一只在草地上玩耍的可爱小猫") String prompt) {
        ImagePrompt imagePrompt = new ImagePrompt(prompt);
        ImageResponse response = imageModel.call(imagePrompt);
        String imageUrl = response.getResult().getOutput().getUrl();
        return "redirect:" + imageUrl;
    }

    @GetMapping("/text2imageUrl2")
    public String text2imageUrl(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(defaultValue = "wan2.5-t2i-preview") String model,
            @RequestParam(value = "prompt", defaultValue = "一只在草地上玩耍的可爱小猫") String prompt) {
        ImageOptions options = ImageOptionsBuilder.builder()
                .model(model)
                .width(1024)
                .height(1024)
                .build();

        ImagePrompt imagePrompt = new ImagePrompt(prompt, options);
        ImageResponse response = imageModel.call(imagePrompt);
        String imageUrl = response.getResult().getOutput().getUrl();

        return "生成的图片URL: " + imageUrl + "<br><img src='" + imageUrl + "' alt='生成的图片'>";
    }

    /**
     * 核心功能：基于文档的智能问答
     * 就像把书给助理看，然后问他相关问题
     */
    @GetMapping("/mult")
    public String mult(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(defaultValue = "百年孤独") String fileContent,
            @RequestParam(value = "prompt", defaultValue = "这本书讲了啥") String prompt) {
        // 1. 从知识库中取出指定的"书"

        // 2. 给AI明确的指令：基于这本书回答问题
        String realPrompt = "请你扮演一个专业的文档分析助手。请严格基于我提供的文档内容来回答问题。\n\n" +
                "文档内容如下：   fileContent + \n\n" +
                "我的问题是：" + fileContent + "\n\n" +
                "回答要求：\n" +
                "1. 如果文档中有相关信息，请准确回答并注明依据\n" +
                "2. 如果文档中没有相关信息，请诚实说'文档中没有提到相关内容'\n" +
                "3. 不要使用文档之外的知识来回答问题";

        // 3. 让AI助理基于文档给出答案
        String answer = chatClient.prompt()
                .user(realPrompt)
                .call()
                .content();
        return answer;
    }

    @Autowired
    private DashScopeAgent dashScopeAgent;

    @Value("${spring.ai.dashscope.agent.app-id}")
    private String appId;//agent的id

    @Value("${spring.ai.dashscope.rag.index-name}")
    private String indexName; //知识库名称

    /**
     * 需要在 百炼上创建 智能体 复制 appid和workid
     * <p>
     * 使用云端的 知识库
     */
    @GetMapping("/agent")
    public String agent(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(value = "prompt", defaultValue = "小张他是那一年出生的") String prompt) {
        // 1. 从知识库中取出指定的"书"
        DashScopeAgentOptions options = DashScopeAgentOptions.builder().withAppId(appId).build();
        ChatResponse chatResponse = dashScopeAgent.call(new Prompt(prompt, options));
        String content = chatResponse.getResult().getOutput().getText();
        return content;
    }

  //  @Autowired
    private DashScopeApi dashScopeApi;

    @Autowired
    private ChatClient.Builder builder;

    @GetMapping("/importFile2rga")
    public String importFile2rga(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            String filePath) {
        List<Document> documentList = new DashScopeDocumentCloudReader(filePath, dashScopeApi, null).get();

        DashScopeCloudStore store = new DashScopeCloudStore(dashScopeApi, new DashScopeStoreOptions(indexName));
        store.add(documentList);
        return "导入文件到云端知识库";
    }

    private String systemTemplate = """
                上下文信息如下：
                {question_answer_context}
                根据上下文的信息,回答用户的问题
            """;

    //知识库检索
    @GetMapping("/chatExtRag")
    public Flux<ChatResponse> chatExtRag(
            @RequestParam(defaultValue = "default") String userId,
            @RequestParam(defaultValue = "admin") String sessionId,
            @RequestParam(value = "prompt", defaultValue = "小张他是那一年出生的") String prompt) {
        // 1. 从知识库中取出指定的"书"
        DashScopeDocumentRetrieverOptions options = DashScopeDocumentRetrieverOptions.builder().withIndexName(indexName).build();
        DashScopeDocumentRetriever retriever = new DashScopeDocumentRetriever(dashScopeApi, options);
        ChatClient chatClientRag = builder.defaultAdvisors(new DocumentRetrievalAdvisor(retriever, systemTemplate)).build();
        Flux<ChatResponse> chatResponseFlux = chatClientRag.prompt().user(prompt).stream().chatResponse();
        return chatResponseFlux;
    }
}
